home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / ipServer / udp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-22  |  27.1 KB  |  1,033 lines

  1. /* 
  2.  * udp.c --
  3.  *
  4.  *    Routines to handle incoming and outgoing UDP packets
  5.  *    as well as UDP-dependent  routines that implement the 
  6.  *    semantics of the socket operations defined in sockOps.c.
  7.  *
  8.  *    The routines follow the User Datagram Protocol specification
  9.  *    in RFC 768 (Aug. 1980).
  10.  *
  11.  *    Based on 4.3 BSD code:
  12.  *    "@(#)udp_usrreq.c  7.5 (Berkeley) 3/11/88"
  13.  *
  14.  * Copyright 1987 Regents of the University of California
  15.  * All rights reserved.
  16.  * Permission to use, copy, modify, and distribute this
  17.  * software and its documentation for any purpose and without
  18.  * fee is hereby granted, provided that the above copyright
  19.  * notice appear in all copies.  The University of California
  20.  * makes no representations about the suitability of this
  21.  * software for any purpose.  It is provided "as is" without
  22.  * express or implied warranty.
  23.  */
  24.  
  25. #ifndef lint
  26. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/udp.c,v 1.16 91/05/21 17:01:35 mottsmth Exp $ SPRITE (Berkeley)";
  27. #endif not lint
  28.  
  29.  
  30. #include "sprite.h"
  31. #include "dev/net.h"
  32. #include "inet.h"
  33. #include "ipServer.h"
  34. #include "stat.h"
  35. #include "ip.h"
  36. #include "udp.h"
  37. #include "socket.h"
  38. #include "sockInt.h"
  39. #include "route.h"
  40.  
  41. #ifndef KERNEL
  42. #include <dev/pdev.h>
  43. #endif
  44.  
  45. static void        Input();
  46. static unsigned int     GetPort();
  47.  
  48.  
  49. /*
  50.  *----------------------------------------------------------------------
  51.  *
  52.  * UDP_Init --
  53.  *
  54.  *    Causes a handler to be called whenever UDP packets arrive.
  55.  *
  56.  * Results:
  57.  *    None.
  58.  *
  59.  * Side effects:
  60.  *    None.
  61.  *
  62.  *----------------------------------------------------------------------
  63.  */
  64.  
  65. void
  66. UDP_Init()
  67. {
  68.     IP_SetProtocolHandler(NET_IP_PROTOCOL_UDP, Input);
  69. }
  70.  
  71. /*
  72.  *----------------------------------------------------------------------
  73.  *
  74.  * Input --
  75.  *
  76.  *    This routine accepts IP datagrams and processes data for
  77.  *    this protocol.
  78.  *
  79.  * Results:
  80.  *    None.
  81.  *
  82.  * Side effects:
  83.  *    None.
  84.  *
  85.  *----------------------------------------------------------------------
  86.  */
  87.  
  88. /*ARGSUSED*/
  89. static void
  90. Input(netID, packetPtr)
  91.     Rte_NetID    netID;        /* ID of the network the packet arrived on. */
  92.     IPS_Packet    *packetPtr;    /* Packet descriptor. */
  93. {
  94.     register Net_UDPHeader    *udpPtr;
  95.     register Net_IPHeader    *ipPtr;
  96.     Sock_SharedInfo         *sockPtr;
  97.     unsigned            udpLen;
  98.  
  99.     stats.udp.recv.total++;
  100.  
  101.     ipPtr  = packetPtr->ipPtr;
  102.     udpPtr = (Net_UDPHeader *) ((Address) ipPtr + ipPtr->headerLen*4);
  103.  
  104.     udpLen = Net_NetToHostShort(udpPtr->len);
  105.     if (udpLen < sizeof(Net_UDPHeader)) {
  106.     stats.udp.recv.shortLen++;
  107.     free(packetPtr->base);
  108.     return;
  109.     }
  110.     packetPtr->data = ((Address)udpPtr) + sizeof(Net_UDPHeader);
  111.     packetPtr->dataLen = udpLen - sizeof(Net_UDPHeader);
  112.  
  113.     /*
  114.      * While debugging, drop packets from the rwho, sunrpc, and route daemons.
  115.      */
  116.     switch (Net_NetToHostShort(udpPtr->srcPort)) {
  117.     case 111:    /* sunrpc */
  118.     case 513:     /* rhwod */
  119.     case 520:    /* routed */
  120.         stats.udp.recv.daemon++;
  121.         if (ips_Debug) {
  122.         free(packetPtr->base);
  123.         return;
  124.         }
  125.         break;
  126.     }
  127.  
  128.     /*
  129.      * If the packet was sent with a checksum, the checksum will be
  130.      * non-zero.
  131.      */
  132.     if (udpPtr->checksum != 0) {
  133.     Net_IPPseudoHdr        pseudoHdr;
  134.     unsigned short        sum;
  135.  
  136.     /*
  137.      * The checksum is computed for the IP "pseudo-header" and
  138.      * the UDP header and data. When the UDP checksum was calculated,
  139.      * the checksum field in the header was set to zero. When we 
  140.      * recalculate the value, we don't zero the field so the computed 
  141.      * value should be zero if the packet didn't get garbled.
  142.      */
  143.     pseudoHdr.source    = (ipPtr->source);
  144.     pseudoHdr.dest        = (ipPtr->dest);
  145.     pseudoHdr.zero        = 0;
  146.     pseudoHdr.protocol    = ipPtr->protocol;
  147.     pseudoHdr.len        = udpPtr->len;
  148.  
  149.     if (udpLen & 1) {
  150.         ((Address)udpPtr)[udpLen] = 0;
  151.     }
  152.     sum = Net_InetChecksum2(udpLen, (Address)udpPtr, &pseudoHdr);
  153.  
  154.     if (sum != 0) {
  155.         if (ips_Debug) {
  156.         (void) fprintf(stderr, "UDP: checksum %x != 0\n", sum);
  157.         }
  158.  
  159.         stats.udp.recv.badChecksum++;
  160.         free(packetPtr->base);
  161.         return;
  162.     }
  163.     }
  164.     stats.udp.recv.dataLen += udpLen;
  165.  
  166.     if (ips_Debug) {
  167.     (void) fprintf(stderr, 
  168.         "UDP Input: %d bytes, <%x, %d> <-- <%x, %d>; checksum = %x\n",
  169.         udpLen, 
  170.         Net_NetToHostInt(ipPtr->dest), 
  171.         Net_NetToHostShort(udpPtr->destPort), 
  172.         Net_NetToHostInt(ipPtr->source), 
  173.         Net_NetToHostShort(udpPtr->srcPort), 
  174.         udpPtr->checksum);
  175.         
  176.         
  177.     }
  178.  
  179.     sockPtr = Sock_Match(UDP_PROTO_INDEX, ipPtr->dest, 
  180.             udpPtr->destPort, ipPtr->source, udpPtr->srcPort, TRUE);
  181.  
  182.  
  183.     if (sockPtr != (Sock_SharedInfo *) NULL) {
  184.     stats.udp.recv.accepted++;
  185.     stats.udp.recv.acceptLen += udpLen;
  186.     UDP_SocketInput(sockPtr, ipPtr->source, udpPtr->srcPort, packetPtr);
  187.     } else {
  188.     free(packetPtr->base);
  189.     }
  190. }
  191.  
  192.  
  193.  
  194. /*
  195.  *----------------------------------------------------------------------
  196.  *
  197.  * UDP_Output --
  198.  *
  199.  *    This routine formats a UDP packet and causes it to be
  200.  *    delivered using the IP protocol. The UDP header is formatted
  201.  *    and a checksum is computed.
  202.  *
  203.  * Results:
  204.  *    ?    - result from IP_Output.
  205.  *
  206.  * Side effects:
  207.  *    None.
  208.  *
  209.  *----------------------------------------------------------------------
  210.  */
  211.  
  212. ReturnStatus
  213. UDP_Output(localAddr, remoteAddr, packetPtr)
  214.     Net_InetSocketAddr    localAddr;    /* Local socket address. */
  215.     Net_InetSocketAddr    remoteAddr;    /* Address of remote host. */
  216.     register IPS_Packet *packetPtr;    /* Packet descriptor. */
  217. {
  218.     register Net_UDPHeader    *udpPtr;
  219.     Net_IPPseudoHdr        pseudoHdr;
  220.     short            len;
  221.  
  222.     /*
  223.      * If a local address hasn't been assigned yet, use the official
  224.      * address in the packet.
  225.      */
  226.     if (localAddr.address == Net_HostToNetInt(NET_INET_ANY_ADDR)) {
  227.     localAddr.address = Rte_GetOfficialAddr(FALSE);
  228.     }
  229.  
  230.     udpPtr = (Net_UDPHeader *) (packetPtr->data - sizeof(Net_UDPHeader));
  231.     packetPtr->hdr.udpPtr = udpPtr;
  232.     packetPtr->hdrLen = sizeof(Net_UDPHeader);
  233.  
  234.     /*
  235.      * Compute the checksum for the header and pseudo-header.
  236.      */
  237.     len = packetPtr->dataLen + sizeof(Net_UDPHeader);
  238.     pseudoHdr.source    = (localAddr.address);
  239.     pseudoHdr.dest    = (remoteAddr.address);
  240.     pseudoHdr.zero    = 0;
  241.     pseudoHdr.protocol    = NET_IP_PROTOCOL_UDP;
  242.     pseudoHdr.len    = Net_HostToNetShort(len);
  243.     udpPtr->len        = pseudoHdr.len;
  244.     udpPtr->srcPort    = (localAddr.port);
  245.     udpPtr->destPort    = (remoteAddr.port);
  246.     udpPtr->checksum    = 0;
  247.     udpPtr->checksum    = Net_InetChecksum2((int) len, (Address)udpPtr, 
  248.                     &pseudoHdr);
  249.     if (udpPtr->checksum == 0) {
  250.     udpPtr->checksum = 0xFFFF;
  251.     }
  252.  
  253.     IP_FormatPacket(NET_IP_PROTOCOL_UDP, NET_UDP_TTL, localAddr.address, 
  254.             remoteAddr.address, packetPtr);
  255.  
  256.     if (ips_Debug) {
  257.     (void) fprintf(stderr,
  258.     "UDP_Output: %d bytes, <%x, %d> --> <%x, %d>\n",
  259.         Net_NetToHostShort(pseudoHdr.len), 
  260.         Net_NetToHostInt(localAddr.address), 
  261.         Net_NetToHostShort(localAddr.port),
  262.         Net_NetToHostInt(remoteAddr.address), 
  263.         Net_NetToHostShort(remoteAddr.port));
  264.     }
  265.     stats.udp.send.total++;
  266.     stats.udp.send.dataLen += packetPtr->dataLen;
  267.  
  268.     (void) IP_Output(packetPtr, TRUE);
  269.  
  270.     return(SUCCESS);
  271. }
  272.  
  273.  
  274. /*
  275.  *----------------------------------------------------------------------
  276.  *
  277.  * UDP_SocketOpen --
  278.  *
  279.  *    Does UDP-specific actions for opening a new socket. A port is 
  280.  *    assigned in case the client never does bind or connect operations 
  281.  *    on the socket.
  282.  *
  283.  * Results:
  284.  *    SUCCESS        - always returned.
  285.  *
  286.  * Side effects:
  287.  *    The socket is made ready for sending and receiving UDP packets.
  288.  *
  289.  *----------------------------------------------------------------------
  290.  */
  291.  
  292. /*ARGSUSED*/
  293. ReturnStatus
  294. UDP_SocketOpen(sockPtr, userID)
  295.     Sock_SharedInfo    *sockPtr;    /* Socket to be opened. */
  296.     int            userID;        /* Client's user ID. Ignored. */
  297. {
  298.     sockPtr->local.port = GetPort(Net_HostToNetInt(NET_INET_ANY_ADDR));
  299.     sockPtr->state = READY;
  300.     Sock_BufAlloc(sockPtr, SOCK_RECV_BUF, UDP_MAX_DATAGRAM_SIZE);
  301.     Sock_BufAlloc(sockPtr, SOCK_SEND_BUF, UDP_MAX_DATAGRAM_SIZE);
  302.     return(SUCCESS);
  303. }
  304.  
  305.  
  306. /*
  307.  *----------------------------------------------------------------------
  308.  *
  309.  * UDP_SocketClose --
  310.  *
  311.  *    Removes data from the socket's read and write queues.
  312.  *
  313.  * Results:
  314.  *    SUCCESS        - always returned.
  315.  *
  316.  * Side effects:
  317.  *    Deallocates buffers in the read and write queues.
  318.  *
  319.  *----------------------------------------------------------------------
  320.  */
  321.  
  322. ReturnStatus
  323. UDP_SocketClose(sockPtr)
  324.     register Sock_SharedInfo    *sockPtr;    /* Socket to be closed. */
  325. {
  326.     Sock_BufRemove(sockPtr, SOCK_RECV_BUF, -1);
  327.     Sock_BufRemove(sockPtr, SOCK_SEND_BUF, -1);
  328.     return(SUCCESS);
  329. }
  330.  
  331.  
  332. /*
  333.  *----------------------------------------------------------------------
  334.  *
  335.  * UDP_ReadRequest --
  336.  *
  337.  *    Handle a read request from a client accessing the UDP pseudo-device.
  338.  *    This is an optimized handling of the request-response protocol and
  339.  *    the buffering structures associated with UDP.  Basically there is
  340.  *    just a list of packets associated with the socket, and we point
  341.  *    the kernel at the first one and then remove it.
  342.  *
  343.  *    This should be cleaned up so it isn't quite so pseudo-device
  344.  *    dependent - especially if UDP is moved into the kernel.
  345.  * Results:
  346.  *    None.
  347.  *
  348.  * Side effects:
  349.  *    Removes the first packet from the list.
  350.  *
  351.  *----------------------------------------------------------------------
  352.  */
  353. #ifndef KERNEL
  354. void
  355. UDP_ReadRequest(privPtr, requestPtr, streamID)
  356.     Sock_PrivInfo *privPtr;    /* Socket state */
  357.     Pdev_Request *requestPtr;    /* Pseudo-device request */
  358.     int streamID;        /* Request-response stream */
  359. {
  360.     Pdev_Reply    reply;
  361.     Sock_SharedInfo    *sharePtr = privPtr->sharePtr;
  362.     Sock_BufInfo    *bufInfoPtr;
  363.     Sock_BufDataInfo   *dataPtr = (Sock_BufDataInfo *)NULL;
  364.  
  365.     reply.replySize = 0;
  366.     reply.status = SUCCESS;
  367.     /*
  368.      * Error checking.
  369.      */
  370.     if (requestPtr->hdr.replySize < 0) {
  371.     reply.status = GEN_INVALID_ARG;
  372.     reply.replyBuf = (Address) NULL;
  373.     goto readReply;
  374.     }
  375.     if (sharePtr->error != SUCCESS) {
  376.     reply.status = sharePtr->error;
  377.     sharePtr->error = SUCCESS;
  378.     goto readReply;
  379.     }
  380.     if ((sharePtr->state != READY) &&
  381.     (sharePtr->state != CONNECTED)) {
  382.     reply.status = NET_BAD_OPERATION;
  383.     goto readReply;
  384.     }
  385.     if (privPtr->recvFlags & NET_OUT_OF_BAND) {
  386.     reply.status = NET_BAD_OPERATION;
  387.     goto readReply;
  388.     }
  389.     /*
  390.      * Take the first packet from the socket buffer.
  391.      */
  392.     bufInfoPtr = &sharePtr->recvBuf;
  393.     if (List_IsEmpty(&bufInfoPtr->links)) {
  394.     if (Sock_IsRecvStopped(sharePtr)) {
  395.         reply.status = SUCCESS;
  396.     } else {
  397.         reply.status = FS_WOULD_BLOCK;
  398.     }
  399.     goto readReply;
  400.     }
  401.     dataPtr = (Sock_BufDataInfo *)List_First(&bufInfoPtr->links);
  402.     /*
  403.      * Set up the reply to reference the packet directly.
  404.      */
  405.     reply.replyBuf = dataPtr->bufPtr;
  406.     if (requestPtr->hdr.replySize > dataPtr->len) {
  407.     reply.replySize = dataPtr->len;
  408.     } else {
  409.     reply.replySize = requestPtr->hdr.replySize;
  410.     }
  411.     /*
  412.      * Save the address for recvfrom() emulation
  413.      */
  414.     privPtr->recvFrom = dataPtr->address;
  415. readReply:
  416.     /*
  417.      * Reply to the client.  The kernel will copy the data from
  418.      * the packet to the clients buffer as part of the reply.
  419.      */
  420.     reply.selectBits = Sock_Select(privPtr, TRUE); 
  421.     if (ips_Debug) {
  422.     fprintf(stderr, "UDP_ReadRequest: %d bytes, select 0x%x, status 0x%x\n",
  423.         reply.replySize, reply.selectBits, reply.status);
  424.     }
  425.     PdevReply(streamID, &reply, "read");
  426.     if (dataPtr != (Sock_BufDataInfo *) NULL) {
  427.     /*
  428.      * Nuke the packet.
  429.      */
  430.     if ((privPtr->recvFlags & SOCK_BUF_PEEK) == 0) {
  431.         bufInfoPtr->size -= dataPtr->len;
  432.         List_Remove((List_Links *) dataPtr);
  433.         free(dataPtr->base);
  434.         free(dataPtr);
  435.     } else {
  436.         privPtr->recvFlags &= ~SOCK_BUF_PEEK;
  437.     }
  438.     }
  439. }
  440. #endif /* not KERNEL */
  441.  
  442.  
  443. /*
  444.  *----------------------------------------------------------------------
  445.  *
  446.  * UDP_SocketRead --
  447.  *
  448.  *    THIS HAS BEEN REPLACED BY UDP_ReadRequest
  449.  *
  450.  *    Supplies data to a client doing a read on a UDP socket.
  451.  *    Normally the packet data is  copied to the buffer. If the
  452.  *    packet is smaller than the buffer, no additional packets 
  453.  *    are read so the client will get a short read. If the buffer
  454.  *    is too small, the remaining data in the packet is not saved 
  455.  *    for the next read. Normally, the packet is removed from the
  456.  *    queue and the memory is deallocated once it is read. This
  457.  *    is not the case when the flag NET_PEEK is given.
  458.  *
  459.  * Results:
  460.  *    SUCCESS            - the data were copied to the buffer.
  461.  *    FS_WOULD_BLOCK        - nothing to read.
  462.  *    NET_BAD_OPERATION    - tried to read out-of-band data (not
  463.  *                  defined for this protocol).
  464.  *              
  465.  * Side effects:
  466.  *    The read queue is shortened.
  467.  *
  468.  *----------------------------------------------------------------------
  469.  */
  470.  
  471. ReturnStatus
  472. UDP_SocketRead(privPtr, bufSize, buffer, amountReadPtr)
  473.     Sock_PrivInfo    *privPtr;    /* Ptr to socket's per-process info. */
  474.     int        bufSize;        /* # of bytes in buffer. */
  475.     Address    buffer;            /* Place to put the data. */
  476.     int        *amountReadPtr;        /* # of bytes actually put in buffer. */
  477. {
  478.     ReturnStatus status;
  479.     Sock_SharedInfo    *sharePtr = privPtr->sharePtr;
  480.  
  481.     if ((sharePtr->state != READY) && (sharePtr->state != CONNECTED)) {
  482.     return(NET_BAD_OPERATION);
  483.     }
  484.  
  485.     if (privPtr->recvFlags & NET_OUT_OF_BAND) {
  486.     return(NET_BAD_OPERATION);
  487.     }
  488.  
  489.     status = Sock_BufFetch(sharePtr, privPtr->recvFlags, bufSize, buffer, 
  490.         amountReadPtr, &privPtr->recvFrom);
  491.  
  492.     /*
  493.      * Clear the recvFlags because they are only good for 1 read operation.
  494.      */
  495.     if (status == SUCCESS) {
  496.     privPtr->recvFlags = 0;
  497.     }
  498.  
  499.     return(status);
  500. }
  501.  
  502.  
  503. /*
  504.  *----------------------------------------------------------------------
  505.  *
  506.  * UDP_SocketInput --
  507.  *
  508.  *    This routine is called when a UDP packet arrives from the network.
  509.  *    The packet is appended to the socket's read queue and the client
  510.  *    is notified that there's data to be read.
  511.  *
  512.  * Results:
  513.  *    None.
  514.  *
  515.  * Side effects:
  516.  *    New data is added to the read queue. The waiting client is
  517.  *    woken up. The packet is freed if the buffer is full.
  518.  *
  519.  *----------------------------------------------------------------------
  520.  */
  521.  
  522. void
  523. UDP_SocketInput(sockPtr, srcAddr, srcPort, packetPtr)
  524.     Sock_SharedInfo    *sockPtr;    /* Socket that should get the data. */
  525.     Net_InetAddress    srcAddr;    /* IP address of sender. */
  526.     unsigned int    srcPort;    /* UDP port of sender. */
  527.     IPS_Packet        *packetPtr;    /* Packet descriptor. */
  528. {
  529.     Net_InetSocketAddr    sockAddr;
  530.     int            amtWritten;
  531.  
  532.     sockAddr.address = srcAddr;
  533.     sockAddr.port = srcPort;
  534.     if ((Sock_BufAppend(sockPtr, SOCK_RECV_BUF, TRUE, packetPtr->dataLen, 
  535.         packetPtr->data, packetPtr->base, &sockAddr, &amtWritten) 
  536.     == SUCCESS) && (amtWritten == packetPtr->dataLen)) {
  537.     Sock_NotifyWaiter(sockPtr, FS_READABLE);
  538.     } else {
  539.     free(packetPtr->base);
  540.     }
  541. }
  542.  
  543.  
  544. /*
  545.  *----------------------------------------------------------------------
  546.  *
  547.  * UDP_WriteRequest --
  548.  *
  549.  *    Handle a request to write a UDP datagram to the network.
  550.  *    (This replaces UDP_SocketWrite).
  551.  *
  552.  * Results:
  553.  *    SUCCESS            - the data were sent.
  554.  *    NET_BAD_OPERATION    - the send flags were not 0 (the flag
  555.  *                  values aren't valid for this operation).
  556.  *    ?            - status from UDP_Output.
  557.  *
  558.  * Side effects:
  559.  *    The data will be sent in a packet.
  560.  *
  561.  *----------------------------------------------------------------------
  562.  */
  563.  
  564. ReturnStatus
  565. UDP_WriteRequest(privPtr, procID, bufSize, buffer, amtWrittenPtr)
  566.     register Sock_PrivInfo    *privPtr;
  567.     Proc_PID procID;
  568.     int bufSize;
  569.     char *buffer;
  570.     int *amtWrittenPtr;
  571. {
  572.     register Sock_SharedInfo *sharePtr = privPtr->sharePtr;
  573.     register int headerLen;
  574.     IPS_Packet packet;
  575.  
  576.     *amtWrittenPtr = 0;
  577.     if (bufSize > UDP_MAX_DATAGRAM_SIZE) {
  578.     return(FS_BUFFER_TOO_BIG);
  579.     }
  580.     if ((sharePtr->state != READY) && (sharePtr->state != CONNECTED)) {
  581.     return(NET_BAD_OPERATION);
  582.     }
  583.     /*
  584.      * Do sendto() emulation.  IOC_NET_SEND_INFO may have been used
  585.      * to set the address to which to send this packet.  sendto cannot
  586.      * be used if the socket is connected.
  587.      */
  588.     if (privPtr->sendInfoValid) {
  589.     /*
  590.      * The send info flags are not valid for UDP sockets.
  591.      */
  592.     if (privPtr->sendInfo.flags != 0) {
  593.         return(NET_BAD_OPERATION);
  594.     }
  595.     privPtr->sendInfoValid = FALSE;
  596.     if (privPtr->sendInfo.addressValid) {
  597.         if (sharePtr->state == CONNECTED) {
  598.         return(NET_ALREADY_CONNECTED);
  599.         }
  600.         sharePtr->sentTo = privPtr->sendInfo.address.inet;
  601.             if (sharePtr->sentTo.address == 
  602.             Net_HostToNetInt(NET_INET_BROADCAST_ADDR) &&
  603.         !(sharePtr->options & NET_OPT_BROADCAST)) {
  604.         return(NET_BAD_OPERATION);
  605.         }
  606.     } else {
  607.         /*
  608.          * If the socket's not connected, we don't have a valid 
  609.          * destination address.
  610.          */
  611.         if (sharePtr->state != CONNECTED) {
  612.         return(NET_NOT_CONNECTED);
  613.         }
  614.         sharePtr->sentTo = sharePtr->remote;
  615.     }
  616.  
  617.     } else {
  618.     if (sharePtr->state != CONNECTED) {
  619.         return(NET_NOT_CONNECTED);
  620.     }
  621.     sharePtr->sentTo = sharePtr->remote;
  622.     }
  623.     /*
  624.      * Initialize packet referencing data in place.
  625.      */
  626.     headerLen = sizeof(Net_UDPHeader) + NET_IP_MAX_HDR_SIZE +
  627.             sizeof(IPS_PacketNetHdr);
  628.     packet.dataLen = bufSize;
  629.     packet.totalLen = bufSize + headerLen;
  630.     packet.data = buffer;
  631.     packet.base = packet.dbase = buffer - headerLen;
  632.  
  633.     *amtWrittenPtr = bufSize;
  634.     return(UDP_Output(sharePtr->local, sharePtr->sentTo, &packet));
  635. }
  636.  
  637.  
  638. /*
  639.  *----------------------------------------------------------------------
  640.  *
  641.  * UDP_SocketWrite --
  642.  *
  643.  *    Takes data from a write call by a client and causes the data
  644.  *    to be sent out on the network.
  645.  *
  646.  * Results:
  647.  *    SUCCESS            - the data were sent.
  648.  *    NET_BAD_OPERATION    - the send flags were not 0 (the flag
  649.  *                  values aren't valid for this operation).
  650.  *    ?            - status from UDP_Output.
  651.  *
  652.  * Side effects:
  653.  *    The data will be sent in a packet.
  654.  *
  655.  *----------------------------------------------------------------------
  656.  */
  657.  
  658. ReturnStatus
  659. UDP_SocketWrite(privPtr, packetPtr, amtWrittenPtr)
  660.     Sock_PrivInfo    *privPtr;
  661.     IPS_Packet    *packetPtr;        /* Packet containing data to be
  662.                      * sent on the network. */
  663.     int        *amtWrittenPtr;        /* # of bytes sent to the remote host.*/
  664. {
  665.     ReturnStatus    status;
  666.     Sock_SharedInfo    *sharePtr = privPtr->sharePtr;
  667.  
  668.     *amtWrittenPtr = 0;
  669.  
  670.     if (packetPtr->dataLen > 
  671.          Sock_BufSize(sharePtr, SOCK_SEND_BUF, SOCK_BUF_MAX_SIZE)) {
  672.     return(FS_BUFFER_TOO_BIG);
  673.     }
  674.  
  675.     if ((sharePtr->state != READY) && (sharePtr->state != CONNECTED)) {
  676.     return(NET_BAD_OPERATION);
  677.     }
  678.  
  679.  
  680.     if (privPtr->sendInfoValid) {
  681.     /*
  682.      * The send info flags are not valid for UDP sockets.
  683.      */
  684.     if (privPtr->sendInfo.flags != 0) {
  685.         return(NET_BAD_OPERATION);
  686.     }
  687.  
  688.     /*
  689.      * See if the client has given us an explicit address about
  690.      * where to send the packet. 
  691.      */
  692.  
  693.     privPtr->sendInfoValid = FALSE;
  694.     if (privPtr->sendInfo.addressValid) {
  695.         /*
  696.          * If the socket's connected, the user can't specify a different
  697.          * destination.
  698.          */
  699.         if (sharePtr->state == CONNECTED) {
  700.         return(NET_ALREADY_CONNECTED);
  701.         }
  702.         sharePtr->sentTo = privPtr->sendInfo.address.inet;
  703.  
  704.     } else {
  705.         /*
  706.          * If the socket's not connected, we don't have a valid 
  707.          * destination address.
  708.          */
  709.         if (sharePtr->state != CONNECTED) {
  710.         return(NET_NOT_CONNECTED);
  711.         }
  712.         sharePtr->sentTo = sharePtr->remote;
  713.     }
  714.  
  715.     } else {
  716.     if (sharePtr->state != CONNECTED) {
  717.         return(NET_NOT_CONNECTED);
  718.     }
  719.     sharePtr->sentTo = sharePtr->remote;
  720.     }
  721.  
  722.     status = UDP_Output(sharePtr->local, sharePtr->sentTo, packetPtr);
  723.     free(packetPtr->base);
  724.  
  725.     if (status == SUCCESS) {
  726.     *amtWrittenPtr = packetPtr->dataLen;
  727.     }
  728.     return(status);
  729. }
  730.  
  731.  
  732. /*
  733.  *----------------------------------------------------------------------
  734.  *
  735.  * UDP_SocketSelect --
  736.  *
  737.  *    Handles UDP-specific checks to see if a socket is ready for
  738.  *    reading. The socket is always writable.
  739.  *
  740.  * Results:
  741.  *    An or'd combination of FS_READBLE and FS_WRITABLE.
  742.  *
  743.  * Side effects:
  744.  *    None.
  745.  *
  746.  *----------------------------------------------------------------------
  747.  */
  748.  
  749. int
  750. UDP_SocketSelect(sockPtr)
  751.     Sock_SharedInfo *sockPtr;    /* Socket to check the readiness of. */
  752. {
  753.     int flags = FS_WRITABLE;
  754.  
  755.     /*
  756.      * The socket is readable only if there's data in the read queue.
  757.      */
  758.     if (Sock_BufSize(sockPtr, SOCK_RECV_BUF, SOCK_BUF_USED) > 0) {
  759.     flags |= FS_READABLE;
  760.     }
  761.     return(flags);
  762. }
  763.  
  764.  
  765. /*
  766.  *----------------------------------------------------------------------
  767.  *
  768.  * UDP_SocketBind --
  769.  *
  770.  *    Does UDP-specific stuff for assigning the local address of a socket.
  771.  *
  772.  * Results:
  773.  *    SUCCESS            - the operation was successful.
  774.  *    NET_ADDRESS_NOT_AVAIL    - the caller gave an address that doesn't
  775.  *                  correspond to this host.
  776.  *    NET_ADDRESS_IN_USE    - the given address is already in use.
  777.  *    GEN_NO_PERMISSION    - tried to bind a port that is reserved
  778.  *                  to the super-user.
  779.  *
  780.  * Side effects:
  781.  *    The local socket address for a socket is assigned.
  782.  *
  783.  *----------------------------------------------------------------------
  784.  */
  785.  
  786. ReturnStatus
  787. UDP_SocketBind(sockPtr, addrPtr, userID)
  788.     register Sock_SharedInfo *sockPtr;    /* Socket to be bound. */
  789.     Net_InetSocketAddr    *addrPtr;    /* Local address to assign to the 
  790.                      * socket. */
  791.     int        userID;            /* User ID of the process. */
  792. {
  793.     Net_InetSocketAddr    temp;
  794.     temp = *addrPtr;
  795.  
  796.     /*
  797.      * If a specific Inetnet address is given, make sure it is valid for
  798.      * this host (i.e. it is one of the addresses assigned to the host).
  799.      */
  800.     if (temp.address != Net_HostToNetInt(NET_INET_ANY_ADDR)) {
  801.     if (!Rte_ValidateAddress(temp.address)) {
  802.         return(NET_ADDRESS_NOT_AVAIL);
  803.     }
  804.     }
  805.  
  806.     if (temp.port == 0) {
  807.     temp.port = GetPort(temp.address);
  808.     } else {
  809.     Boolean wildcard;
  810.  
  811.     /*
  812.      * Make sure the given port is OK to use. If the port # is in
  813.      * the reserved range then make sure the user has super-user
  814.      * privileges. 
  815.      */
  816.  
  817.     if ((Net_NetToHostShort(temp.port) < INET_PRIV_PORTS) && 
  818.         (userID != PROC_SUPER_USER_ID)) {
  819.         return(GEN_NO_PERMISSION);
  820.     }
  821.  
  822.     /*
  823.      * Check for the uniqueness of the new local <address,port> tuple
  824.      * among all UDP sockets.  The REUSE_ADDR option specifies the
  825.      * strictness of the check.  If the option is not set, then the
  826.      * local tuple can't be used by us if any other UDP socket is
  827.      * using it.  A looser check is made if the option is set:  we can
  828.      * use the local tuple even if it is used by other sockets but
  829.      * only if their remote tuple is not the <NET_INET_ANY_ADDR,0>
  830.      * wildcard.
  831.      */
  832.  
  833.     if (Sock_IsOptionSet(sockPtr, NET_OPT_REUSE_ADDR)) {
  834.         wildcard = FALSE;
  835.     } else {
  836.         wildcard = TRUE;
  837.     }
  838.     if (Sock_Match(UDP_PROTO_INDEX, temp.address, temp.port,
  839.             Net_HostToNetInt(NET_INET_ANY_ADDR), 0, wildcard) !=
  840.                 (Sock_SharedInfo *) NULL) {
  841.  
  842.         return(NET_ADDRESS_IN_USE);
  843.     }
  844.     }
  845.  
  846.     sockPtr->local = temp;
  847.     sockPtr->state = READY;
  848.     return(SUCCESS);
  849. }
  850.  
  851.  
  852.  
  853. /*
  854.  *----------------------------------------------------------------------
  855.  *
  856.  * UDP_SocketConnect --
  857.  *
  858.  *    Assigns a remote host <address,port> pair to a socket. 
  859.  *    From now on, only packets from this remote host will be
  860.  *    accepted for this socket.
  861.  *
  862.  * Results:
  863.  *    SUCCESS            - the operation was successful.
  864.  *    NET_ADDRESS_NOT_AVAIL    - an invalid port was specified.
  865.  *    NET_ALREADY_CONNECTED    - the socket is already connected.
  866.  *    NET_ADDRESS_IN_USE    - the <local,remote> pair is already
  867.  *                   in use by another socket.
  868.  *    
  869.  *
  870.  * Side effects:
  871.  *    The remote socket address for a socket is assigned.
  872.  *    The local socket address may also be assigned.
  873.  *
  874.  *----------------------------------------------------------------------
  875.  */
  876.  
  877. /*ARGSUSED*/
  878. ReturnStatus
  879. UDP_SocketConnect(sockPtr, remoteAddrPtr, initialize)
  880.     register Sock_SharedInfo    *sockPtr;    /* Socket to be connected. */
  881.     Net_InetSocketAddr    *remoteAddrPtr;    /* Remote address to send and receive
  882.                      * datagrams from. */
  883.     Boolean        initialize;    /* Ignored. */
  884. {
  885.     Net_InetSocketAddr    remote;
  886.     remote = *remoteAddrPtr;
  887.  
  888.  
  889.     /*
  890.      * If the socket's already connected, disconnect it by zeroing 
  891.      * the remote <address,port> and removing all data in the recv queue.
  892.      */
  893.  
  894.     if (sockPtr->state == CONNECTED) {
  895.     sockPtr->remote.address    = Net_HostToNetInt(NET_INET_ANY_ADDR);
  896.     sockPtr->remote.port    = 0;
  897.     sockPtr->state        = READY;
  898.     Sock_BufRemove(sockPtr, SOCK_RECV_BUF, -1);
  899.     }
  900.  
  901.  
  902.     /*
  903.      * A valid remote port must be specified.
  904.      */
  905.     if (remote.port == 0) {
  906.     return(NET_ADDRESS_NOT_AVAIL);
  907.     }
  908.  
  909.     /*
  910.      * If the wildcard address or the broadcast wildcard are given, then
  911.      * use the official address (explicit or broadcast) for the server.
  912.      */
  913.  
  914.     if (ips_Debug) {
  915.     fprintf(stderr, "Socket_Connect: remote_addr before = %x\n",
  916.             remote.address);
  917.     }
  918.     if (remote.address == Net_HostToNetInt(NET_INET_ANY_ADDR)) {
  919.     remote.address = Rte_GetOfficialAddr(FALSE);
  920.     } else if (remote.address == Net_HostToNetInt(NET_INET_BROADCAST_ADDR)) {
  921.     remote.address = Rte_GetOfficialAddr(TRUE);
  922.     }
  923.     if (ips_Debug) {
  924.     fprintf(stderr, "Socket_Connect: remote_addr after = %x\n",
  925.             remote.address);
  926.     }
  927.  
  928.     if (sockPtr->local.address == Net_HostToNetInt(NET_INET_ANY_ADDR)) {
  929.     Net_InetAddress    localAddr;
  930.  
  931.     /*
  932.      * The socket doesn't have a local address part yet so 
  933.      * use the official address for this server. Make sure the
  934.      * <local <address,port> and remote <address,port> tuple is
  935.      * unique among all open UDP sockets.
  936.      */
  937.  
  938.     localAddr = Rte_GetOfficialAddr(FALSE);
  939.     if (Sock_Match(UDP_PROTO_INDEX, localAddr, 
  940.         sockPtr->local.port, remote.address, remote.port, FALSE) !=
  941.         (Sock_SharedInfo *) NULL) {
  942.         return(NET_ADDRESS_IN_USE);
  943.     }
  944.  
  945.     /*
  946.      * The socket has a unique address tuple. 
  947.      * If a local port has not been chosen yet, assign an unused value.
  948.      */
  949.  
  950.     sockPtr->local.address = localAddr;
  951.     if (sockPtr->local.port == 0) {
  952.         sockPtr->local.port = GetPort(localAddr);
  953.     }
  954.     } else {
  955.     /*
  956.      * The socket has a valid local <address, port>. Make sure the
  957.      * the <local, remote> tuple is unique among all open UDP sockets.
  958.      */
  959.  
  960.     if (Sock_Match(UDP_PROTO_INDEX, sockPtr->local.address, 
  961.         sockPtr->local.port, remote.address, remote.port, FALSE) !=
  962.         (Sock_SharedInfo *) NULL) {
  963.         return(NET_ADDRESS_IN_USE);
  964.     }
  965.     }
  966.     sockPtr->remote    = remote;
  967.     sockPtr->state    = CONNECTED;
  968.  
  969.     return(SUCCESS);
  970. }
  971.  
  972.  
  973. /*
  974.  *----------------------------------------------------------------------
  975.  *
  976.  * UDP_SocketShutdown --
  977.  *
  978.  *    Called when the client will not send any more data on the socket.
  979.  *
  980.  * Results:
  981.  *    None.
  982.  *
  983.  * Side effects:
  984.  *    The socket is prevented from sending data.
  985.  *
  986.  *----------------------------------------------------------------------
  987.  */
  988.  
  989. /*ARGSUSED*/
  990. ReturnStatus
  991. UDP_SocketShutdown(sockPtr, how)
  992.     Sock_SharedInfo     *sockPtr;    /* Socket to be shutdown. */
  993.     int        how;        /* Type of shutdown wanted. */
  994. {
  995.     Sock_StopSending(sockPtr);
  996.     return(SUCCESS);
  997. }
  998.  
  999.  
  1000. /*
  1001.  *----------------------------------------------------------------------
  1002.  *
  1003.  * GetPort --
  1004.  *
  1005.  *    Assign a port for a given address and make sure it doesn't 
  1006.  *    doesn't conflict with an existing socket's binding address.
  1007.  *
  1008.  * Results:
  1009.  *    A new port #.
  1010.  *
  1011.  * Side effects:
  1012.  *    The port value is incremented.
  1013.  *
  1014.  *----------------------------------------------------------------------
  1015.  */
  1016.  
  1017. static unsigned int
  1018. GetPort(localAddr)
  1019.     Net_InetAddress    localAddr;    /* Address to check for uniqueness. */
  1020. {
  1021.     static unsigned int port = INET_PRIV_PORTS;
  1022.  
  1023.     do {
  1024.     port++;
  1025.     if ((port < INET_PRIV_PORTS) || (port > INET_SERVER_PORTS)) {
  1026.         port = INET_PRIV_PORTS;
  1027.     }
  1028.     } while (Sock_Match(UDP_PROTO_INDEX, localAddr, Net_HostToNetShort(port), 
  1029.             Net_HostToNetInt(NET_INET_ANY_ADDR), 0, FALSE) !=
  1030.                 (Sock_SharedInfo *) NULL);
  1031.     return(Net_HostToNetShort(port));
  1032. }
  1033.